<template>
  <div class="bubble-canvas" ref="canvasContainer">
    <div 
      v-for="bubble in bubbles" 
      :key="bubble.id" 
      class="box"
      :style="getBoxStyle(bubble)"
    >
      <div 
        class="ball" 
        :style="getBubbleStyle(bubble)"
        @click="handleBubbleClick(bubble)"
      >
        <div class="bubble-content">
          <div class="bubble-text">{{ bubble.content }}</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, defineProps, defineEmits, watch, nextTick } from 'vue';

// 定义props和emits
const props = defineProps({
  messages: {
    type: Array,
    default: () => []
  }
});

const emit = defineEmits(['bubble-click']);

// 引用DOM元素
const canvasContainer = ref(null);

// 气泡数组
const bubbles = ref([]);

// 容器尺寸
const containerSize = ref({
  width: 0,
  height: 0
});

// 标记组件是否已挂载
let isMounted = false;

// 动画帧请求ID
let animationFrameId = null;

// 增强的气泡类
class Bubble {
  constructor(message, x, y, size = 'medium', zIndex = 1) {
    this.id = message.id;
    this.author = message.author;
    this.content = message.content;
    this.createTime = message.createTime;
    
    // 根据大小设置半径
    if (size === 'large') {
      this.radius = Math.max(100, Math.min(150, 100 + message.content.length / 2));
      this.opacity = 1;
      this.mass = 10;
    } else if (size === 'medium') {
      this.radius = Math.max(70, Math.min(100, 70 + message.content.length / 3));
      this.opacity = 0.8;
      this.mass = 5;
    } else { // small
      this.radius = Math.max(40, Math.min(60, 40 + message.content.length / 4));
      this.opacity = 0.6;
      this.mass = 2;
    }
    
    this.x = x;
    this.y = y;
    this.zIndex = zIndex;
    this.size = size;
    
    // 添加速度属性用于物理模拟
    this.vx = (Math.random() - 0.5) * 2; // 随机初始水平速度
    this.vy = (Math.random() - 0.5) * 2; // 随机初始垂直速度
    
    // 随机颜色搭配 - 粉色系
    const hue1 = 300 + Math.random() * 60; // 粉色系
    const hue2 = 270 + Math.random() * 60; // 紫粉色系
    const lightness1 = 75 + Math.random() * 15; // 更亮的颜色
    
    this.color1 = `hsla(${hue1}, 80%, ${lightness1}%, ${this.opacity})`;
    this.color2 = `hsla(${hue2}, 80%, 65%, ${this.opacity})`;
    
    console.log(`[气泡创建] ID: ${this.id}, 作者: ${this.author}, 大小: ${size}, 位置: (${Math.round(x)}, ${Math.round(y)})`);
  }
}

// 物理模拟参数
const BOUNCE = 1.0; // 反弹系数
const SPEED = 1.2; // 气泡移动速度 - 降低速度减少计算量

// 帧率控制
const FPS = 35; // 限制每秒30帧
const FRAME_INTERVAL = 1000 / FPS;
let lastFrameTime = 0;

// 初始化气泡速度方向
const initializeBubbleDirection = (bubble) => {
  // 随机角度
  const angle = Math.random() * Math.PI * 2;
  // 设置固定速度，只改变方向
  bubble.vx = Math.cos(angle) * SPEED;
  bubble.vy = Math.sin(angle) * SPEED;
};

// 创建气泡
const createBubbles = () => {
  try {
    console.log('[BubbleCanvas] 开始创建气泡，消息数量:', props.messages.length);
    
    // 验证消息列表
    if (!props.messages || props.messages.length === 0) {
      console.warn('[BubbleCanvas] 消息列表为空，不创建气泡');
      bubbles.value = [];
      return;
    }
    
    // 验证组件是否已挂载
    if (!isMounted || !canvasContainer.value) {
      console.warn('[BubbleCanvas] 组件未挂载或容器不存在，不创建气泡');
      return;
    }
    
    // 清空现有气泡
    bubbles.value = [];
    
    // 获取容器尺寸
    containerSize.value = {
      width: canvasContainer.value.clientWidth || 800,
      height: canvasContainer.value.clientHeight || 500
    };
    console.log('[BubbleCanvas] 容器尺寸:', containerSize.value.width, 'x', containerSize.value.height);
    
    // 分配不同大小的气泡
    const totalMessages = props.messages.length;
    console.log('[BubbleCanvas] 开始创建', totalMessages, '个气泡');
    
    // 创建一个大气泡
    if (totalMessages > 0 && props.messages[0]) {
      const mainMessage = props.messages[0];
      const centerX = containerSize.value.width / 2;
      const centerY = containerSize.value.height / 2;
      
      // 创建主气泡
      const mainBubble = new Bubble(mainMessage, centerX, centerY, 'large', 10);
      initializeBubbleDirection(mainBubble);
      bubbles.value.push(mainBubble);
    }
    
    // 创建中等大小的气泡
    const mediumCount = Math.min(totalMessages - 1, 3);
    for (let i = 0; i < mediumCount; i++) {
      if (props.messages[i + 1]) {
        const message = props.messages[i + 1];
        
        // 在主气泡周围分布
        const angle = (Math.PI * 2 / mediumCount) * i;
        const distance = 150 + Math.random() * 50;
        const x = containerSize.value.width / 2 + Math.cos(angle) * distance;
        const y = containerSize.value.height / 2 + Math.sin(angle) * distance;
        
        // 创建中等气泡
        const mediumBubble = new Bubble(message, x, y, 'medium', 5);
        initializeBubbleDirection(mediumBubble);
        bubbles.value.push(mediumBubble);
      }
    }
    
    // 创建小气泡
    const smallCount = Math.min(totalMessages - mediumCount - 1, 5);
    for (let i = 0; i < smallCount; i++) {
      if (props.messages[i + mediumCount + 1]) {
        const message = props.messages[i + mediumCount + 1];
        
        // 随机分布在容器中
        const x = 40 + Math.random() * (containerSize.value.width - 80);
        const y = 40 + Math.random() * (containerSize.value.height - 80);
        
        // 创建小气泡
        const smallBubble = new Bubble(message, x, y, 'small', 1);
        initializeBubbleDirection(smallBubble);
        bubbles.value.push(smallBubble);
      }
    }
    
    console.log('[BubbleCanvas] 成功创建气泡:', bubbles.value.length, '个');
  } catch (error) {
    console.error('[BubbleCanvas] 创建气泡时发生错误:', error);
    // 出错时清空气泡数组
    bubbles.value = [];
  }
};

// 监听messages变化
watch(() => props.messages, (newMessages) => {
  console.log('[BubbleCanvas] messages变化，数量:', newMessages.length);
  if (newMessages && newMessages.length > 0) {
    // 当消息列表有数据时初始化气泡
    createBubbles();
    // 如果动画没有运行，启动动画
    if (!animationFrameId && isMounted) {
      updateBubbles();
    }
  } else {
    console.log('[BubbleCanvas] 消息列表为空，不初始化气泡');
    // 清空气泡数组
    bubbles.value = [];
  }
}, { deep: true, immediate: true });

// 处理窗口大小变化
const handleResize = () => {
  // 重新计算容器尺寸
  if (canvasContainer.value) {
    containerSize.value = {
      width: canvasContainer.value.clientWidth,
      height: canvasContainer.value.clientHeight
    };
    
    // 重新定位气泡
    bubbles.value.forEach(bubble => {
      // 确保气泡在新尺寸范围内
      bubble.x = Math.min(Math.max(bubble.radius, bubble.x), containerSize.value.width - bubble.radius);
      bubble.y = Math.min(Math.max(bubble.radius, bubble.y), containerSize.value.height - bubble.radius);
    });
  }
};

// 获取气泡容器样式
const getBoxStyle = (bubble) => {
  return {
    left: `${bubble.x}px`,
    top: `${bubble.y}px`,
    zIndex: bubble.zIndex,
  };
};

// 获取气泡样式
const getBubbleStyle = (bubble) => {
  return {
    width: `${bubble.radius * 2}px`,
    height: `${bubble.radius * 2}px`,
    animationDelay: `${bubble.animationDelay}s`,
    background: `radial-gradient(circle at 77% 30%, white 5px, ${bubble.color1} 8%, ${bubble.color2} 60%, ${bubble.color1} 100%)`,
    boxShadow: `inset 0 0 20px #fff,
                inset 10px 0 46px #eaf5fc,
                inset 88px 0px 60px #c2d8fe,
                inset -20px -60px 100px #fde9ea,
                inset 0 50px 140px #fde9ea,
                0 0 90px #fff`,
    opacity: bubble.opacity,
    border: '1px solid rgba(255, 255, 255, 0.5)',
    backdropFilter: 'blur(5px)',
  };
};

// 获取阴影样式
const getShadowStyle = (bubble) => {
  return {
    width: `${bubble.radius * 1.5}px`,
    height: `${bubble.radius * 0.4}px`,
    opacity: bubble.opacity * 0.8,
    animationDelay: `${bubble.animationDelay}s`,
  };
};

// 获取短内容（用于气泡显示）
const getShortContent = (content) => {
  return content.length > 20 ? content.substring(0, 20) + '...' : content;
};

// 处理气泡点击
const handleBubbleClick = (bubble) => {
  // 查找对应的原始消息
  const message = props.messages.find(m => m.id === bubble.id);
  if (message) {
    emit('bubble-click', message);
  }
};

// 更新气泡内容，但不改变气泡位置和大小
// 这个方法会被父组件调用，用于定期更新气泡内容
const updateBubbleContents = (newMessages) => {
  if (!bubbles.value.length || !newMessages.length) {
    console.log('[BubbleCanvas] 无法更新气泡内容，气泡或消息为空');
    return;
  }
  
  console.log('[BubbleCanvas] 开始更新气泡内容，保持位置不变');
  
  // 创建一个消息ID到消息内容的映射
  const messageMap = {};
  newMessages.forEach(msg => {
    messageMap[msg.id] = msg;
  });
  
  // 遍历现有气泡，更新其内容
  bubbles.value.forEach(bubble => {
    // 如果有对应的新消息，更新内容
    if (messageMap[bubble.id]) {
      const newMsg = messageMap[bubble.id];
      bubble.content = newMsg.content;
      bubble.author = newMsg.author;
      bubble.createTime = newMsg.createTime;
      console.log(`[BubbleCanvas] 更新气泡ID: ${bubble.id} 的内容`);
    }
  });
  
  console.log('[BubbleCanvas] 气泡内容更新完成');
};

// 注意: 已在组件底部暴露方法

// 更新气泡位置和处理碰撞
const updateBubbles = (timestamp) => {
  // 如果组件已经卸载或容器不存在，停止动画
  if (!isMounted || !canvasContainer.value || bubbles.value.length === 0) {
    if (animationFrameId) {
      cancelAnimationFrame(animationFrameId);
      animationFrameId = null;
    }
    return;
  }
  
  // 帧率限制 - 检查是否应该跳过这一帧
  if (timestamp - lastFrameTime < FRAME_INTERVAL) {
    // 如果还没到下一帧的时间，继续请求动画帧但不进行计算
    animationFrameId = requestAnimationFrame(updateBubbles);
    return;
  }
  
  // 更新上一帧的时间
  lastFrameTime = timestamp;
  
  try {
    const width = containerSize.value.width;
    const height = containerSize.value.height;
  
    // 更新每个气泡的位置
    bubbles.value.forEach(bubble => {
      // 应用速度，气泡按直线移动
      bubble.x += bubble.vx;
      bubble.y += bubble.vy;
      
      // 边界碰撞检测 - 碰到墙壁反弹
      if (bubble.x - bubble.radius < 0) {
        bubble.x = bubble.radius;
        bubble.vx = Math.abs(bubble.vx); // 反向水平速度
      } else if (bubble.x + bubble.radius > width) {
        bubble.x = width - bubble.radius;
        bubble.vx = -Math.abs(bubble.vx); // 反向水平速度
      }
      
      if (bubble.y - bubble.radius < 0) {
        bubble.y = bubble.radius;
        bubble.vy = Math.abs(bubble.vy); // 反向垂直速度
      } else if (bubble.y + bubble.radius > height) {
        bubble.y = height - bubble.radius;
        bubble.vy = -Math.abs(bubble.vy); // 反向垂直速度
      }
    });
    
    // 使用网格分区优化碰撞检测，只检查可能碰撞的气泡
    // 每两帧才进行一次碰撞检测，进一步减少CPU负载
    if (timestamp % (FRAME_INTERVAL * 2) < FRAME_INTERVAL) {
      for (let i = 0; i < bubbles.value.length; i++) {
        const bubbleA = bubbles.value[i];
        
        for (let j = i + 1; j < bubbles.value.length; j++) {
          const bubbleB = bubbles.value[j];
          
          // 快速距离检查 - 先用更简单的计算排除明显不会碰撞的气泡
          const dx = bubbleB.x - bubbleA.x;
          const dy = bubbleB.y - bubbleA.y;
          const radiusSum = bubbleA.radius + bubbleB.radius;
          
          // 如果气泡在x或y方向上的距离已经超过半径之和，就不可能碰撞
          if (Math.abs(dx) > radiusSum || Math.abs(dy) > radiusSum) {
            continue; // 跳过这对气泡的碰撞检测
          }
          
          // 只有可能碰撞的气泡才计算精确距离
          const distance = Math.sqrt(dx * dx + dy * dy);
          const minDistance = radiusSum;
          
          // 如果发生碰撞
          if (distance < minDistance) {
            // 简化的碰撞响应 - 交换速度方向
            const temp = {
              vx: bubbleA.vx,
              vy: bubbleA.vy
            };
            
            bubbleA.vx = bubbleB.vx;
            bubbleA.vy = bubbleB.vy;
            bubbleB.vx = temp.vx;
            bubbleB.vy = temp.vy;
            
            // 分开气泡以防止重叠
            if (distance < minDistance - 1) { // 只在明显重叠时才移动气泡
              const angle = Math.atan2(dy, dx);
              const overlap = minDistance - distance + 0.5; // 减少移动量
              const moveX = Math.cos(angle) * overlap * 0.5;
              const moveY = Math.sin(angle) * overlap * 0.5;
              
              bubbleA.x -= moveX;
              bubbleA.y -= moveY;
              bubbleB.x += moveX;
              bubbleB.y += moveY;
            }
          }
        }
      }
    }
    
    // 仅当组件仍然挂载时继续动画循环
    if (isMounted) {
      animationFrameId = requestAnimationFrame(updateBubbles);
    }
  } catch (error) {
    console.error('[BubbleCanvas] 更新气泡时发生错误:', error);
    if (animationFrameId) {
      cancelAnimationFrame(animationFrameId);
      animationFrameId = null;
    }
  }
};

// 标记组件是否已完成初始化
const isInitialized = ref(false);

// 生命周期钩子
onMounted(() => {
  console.log('[BubbleCanvas] 组件挂载开始');
  
  // 添加窗口大小变化监听
  window.addEventListener('resize', handleResize);
  
  // 标记组件已挂载
  isMounted = true;
  
  // 等待DOM渲染完成
  nextTick(() => {
    console.log('[BubbleCanvas] nextTick 执行，消息数量:', props.messages.length);
    
    // 直接创建气泡并启动动画
    if (canvasContainer.value && props.messages && props.messages.length > 0) {
      console.log('[BubbleCanvas] 开始创建气泡');
      createBubbles();
      
      // 立即开始物理动画
      if (!animationFrameId) {
        console.log('[BubbleCanvas] 启动物理动画');
        updateBubbles();
      }
    } else {
      console.warn('[BubbleCanvas] 消息为空或容器不存在，不创建气泡');
    }
  });
  
  console.log('[BubbleCanvas] 组件挂载完成');
});

onUnmounted(() => {
  console.log('[BubbleCanvas] 组件卸载开始');
  
  // 标记组件已卸载
  isMounted = false;
  
  // 停止动画循环
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId);
    animationFrameId = null;
  }
  
  // 清空气泡数组
  bubbles.value = [];
  
  // 移除窗口大小变化监听
  window.removeEventListener('resize', handleResize);
  
  console.log('[BubbleCanvas] 组件卸载完成');
});

// 清理资源
const cleanup = () => {
  console.log('[BubbleCanvas] 清理资源开始');
  
  try {
    // 停止动画循环
    if (animationFrameId) {
      cancelAnimationFrame(animationFrameId);
      animationFrameId = null;
    }
    
    // 清空气泡数组
    bubbles.value = [];
    
    console.log('[BubbleCanvas] 清理资源完成');
  } catch (error) {
    console.error('[BubbleCanvas] 清理资源时发生错误:', error);
  }
};

// 重新初始化
const reinitialize = () => {
  console.log('[BubbleCanvas] 重新初始化开始');
  
  // 如果组件已经卸载，不执行重新初始化
  if (!isMounted) {
    console.warn('[BubbleCanvas] 组件已卸载，取消重新初始化');
    return;
  }
  
  try {
    // 先清理现有资源
    cleanup();
    
    // 使用 nextTick 确保 DOM 更新完成
    nextTick(() => {
      // 确保容器已经渲染
      setTimeout(() => {
        // 再次检查组件是否仍然挂载
        if (!isMounted) return;
        
        if (canvasContainer.value && props.messages.length > 0) {
          // 初始化气泡
          createBubbles();
          
          // 开始物理动画
          if (!animationFrameId) {
            updateBubbles();
          }
          
          console.log('[BubbleCanvas] 重新初始化完成');
        } else {
          console.warn('[BubbleCanvas] 无法重新初始化，容器或消息不存在');
        }
      }, 100);
    });
  } catch (error) {
    console.error('[BubbleCanvas] 重新初始化时发生错误:', error);
  }
};

// 暴露方法
defineExpose({
  cleanup,
  reinitialize,
  updateBubbleContents
});
</script>

<style scoped>
.bubble-canvas {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 500px;
  overflow: hidden;
  border-radius: 8px;
  /* 粉色背景渐变 */
  background-image: linear-gradient(to bottom right,
    #91defe,
    #99c0f9,
    #bdb6ec,
    #d7b3e3,
    #efb3d5,
    #f9bccc);
  background-size: 100% 100%;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  /* 确保气泡容器有高度 */
  display: block;
}

.box {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
  z-index: 10; /* 确保气泡在页面上可见 */
}

.fade-in {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

.ball {
  position: relative;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: auto;
  cursor: pointer;
  transition: transform 0.2s;
  z-index: 2; /* 确保气泡在页面上可见 */
  box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1), inset 0 0 20px rgba(255, 255, 255, 0.5);
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  border: 1px solid rgba(255, 255, 255, 0.5);
}

.ball:hover {
  transform: scale(1.05);
}

.shadow {
  position: absolute;
  bottom: -10px;
  background: rgba(0, 0, 0, 0.15);
  border-radius: 50%;
  z-index: 1; /* 确保阴影在页面上可见 */
}

.bubble-content {
  padding: 15px;
  text-align: center;
  width: 90%;
  height: 90%;
  overflow: hidden;
  color: #333;
  font-size: 16px;
  line-height: 1.5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  word-break: break-word;
}

.bubble-author {
  font-weight: bold;
  margin-bottom: 5px;
  color: #333;
  font-size: 16px;
}

.bubble-text {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  font-size: 0.8em;
  opacity: 0.9;
}

/* 物理模拟样式不需要关键帧动画 */
</style>
